package com.zxy.ziems.server.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zxy.btp.common.exception.ConditionException;
import com.zxy.btp.common.response.PageResult;
import com.zxy.btp.common.util.JsonUtils;
import com.zxy.ziems.server.convert.AgreementChannelConvert;
import com.zxy.ziems.server.convert.AgreementConvert;
import com.zxy.ziems.server.domain.Agreement;
import com.zxy.ziems.server.domain.AgreementChannel;
import com.zxy.ziems.server.domain.ChannelEquip;
import com.zxy.ziems.server.domain.ChannelField;
import com.zxy.ziems.server.domain.User;
import com.zxy.ziems.server.dto.AgreementChannelDto;
import com.zxy.ziems.server.dto.AgreementChannelQueryDto;
import com.zxy.ziems.server.dto.AgreementDto;
import com.zxy.ziems.server.dto.AgreementQueryDto;
import com.zxy.ziems.server.mapper.AgreementChannelMapper;
import com.zxy.ziems.server.mapper.AgreementMapper;
import com.zxy.ziems.server.service.AgreementChannelService;
import com.zxy.ziems.server.service.AgreementService;
import com.zxy.ziems.server.service.ChannelEquipService;
import com.zxy.ziems.server.service.ChannelFieldService;
import com.zxy.ziems.server.service.UserService;
import com.zxy.ziems.server.vo.AgreementChannelVo;
import com.zxy.ziems.server.vo.AgreementVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName AgreementServiceImpl
 * @Description
 * @Author 邓伟
 * @Date 2023/11/29 10:53
 * @Version 1.0
 */
@Service
public class AgreementChannelServiceImpl extends ServiceImpl<AgreementChannelMapper, AgreementChannel> implements AgreementChannelService {

    @Autowired
    private AgreementChannelMapper agreementChannelMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private ChannelFieldService channelFieldService;
    @Autowired
    private ChannelEquipService channelEquipService;
    @Autowired
    private AgreementMapper agreementMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrUpdate(AgreementChannelDto agreementChannelDto) {
        checkName(agreementChannelDto);
        String channelId = agreementChannelDto.getChannelId();
        AgreementChannel agreementChannel = AgreementChannelConvert.INSTANCE.agreementChannelDtoToAgreementChannel(agreementChannelDto);
        if (StrUtil.isEmpty(channelId)) {
            agreementChannelMapper.insert(agreementChannel);
        }else {
            agreementChannelMapper.updateById(agreementChannel);
        }
        //保存通道参数及点位参数
        channelFieldService.batchInsert(agreementChannel.getChannelId(),agreementChannelDto.getChannelParamList(),agreementChannelDto.getPointParamList());
    }

    @Override
    public void delete(String channelId) {
        //判断是否有下级设备
        QueryWrapper<ChannelEquip> query = new QueryWrapper<>();
        query.lambda().eq(ChannelEquip::getChannelId,channelId);
        long count = channelEquipService.count(query);
        if (count > 0 ) {
            throw new ConditionException("通道下有绑定的设备，不允许删除");
        }
        removeById(channelId);
        //删除参数配置
        QueryWrapper<ChannelField> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ChannelField::getChannelId,channelId);
        channelFieldService.remove(queryWrapper);
    }

    @Override
    public PageResult<AgreementChannelVo> pageList(AgreementChannelQueryDto queryDto) {
        //组装wrapper
        QueryWrapper<AgreementChannel> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().like(ObjectUtil.isNotEmpty(queryDto.getChannelName()),AgreementChannel::getChannelName,queryDto.getChannelName());
        queryWrapper.lambda().orderByDesc(AgreementChannel::getUpdateTime);
        Page<AgreementChannel> page = agreementChannelMapper.selectPage(new Page<>(queryDto.getPageNo(), queryDto.getPageSize()), queryWrapper);
        List<AgreementChannel> records = page.getRecords();
        //空值
        if (ObjectUtil.isEmpty(records)){
            return new PageResult<>(page.getTotal(), Collections.emptyList());
        }
        //查询协议信息
        List<String> agreementIdList = records.stream().map(AgreementChannel::getAgreementId).toList();
        Map<String,String> agreementMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(agreementIdList)){
            List<Agreement> agreementList = agreementMapper.selectBatchIds(agreementIdList);
            agreementMap = agreementList.stream().collect(Collectors.toMap(Agreement::getAgreementId,Agreement::getAgreementName));
        }

        List<String> userIdList = records.stream().map(AgreementChannel::getUpdateUserId).toList();
        //负责人
        Map<String,String> userMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(userIdList)){
            List<User> userList = userService.listByIds(userIdList);
            userMap = userList.stream().collect(Collectors.toMap(User::getUserId,User::getUserName));
        }
        //查询参数信息
        List<String> channelIdList = records.stream().map(AgreementChannel::getChannelId).toList();
        QueryWrapper<ChannelField> query = new QueryWrapper<>();
        query.lambda().in(ChannelField::getChannelId,channelIdList);
        List<ChannelField> channelFieldList = channelFieldService.list(query);
        Map<String, Map<Integer, List<ChannelField>>> map = channelFieldList.stream().collect(Collectors.groupingBy(ChannelField::getChannelId, Collectors.groupingBy(ChannelField::getFieldType)));
        List<AgreementChannelVo> voList = new ArrayList<>();
        for (AgreementChannel agreementChannel : records) {
            AgreementChannelVo agreementChannelVo = AgreementChannelConvert.INSTANCE.agreementChannelToAgreementChannelVo(agreementChannel);
            agreementChannelVo.setUpdateUserName(userMap.get(agreementChannelVo.getUpdateUserId()));
            agreementChannelVo.setAgreementName(agreementMap.get(agreementChannelVo.getAgreementId()));
            //处理参数
            Map<Integer, List<ChannelField>> paramMap = map.get(agreementChannel.getChannelId());
            List<ChannelField> channelParamList = paramMap.get(0);
            List<ChannelField> pointParamList = paramMap.get(1);
            agreementChannelVo.setChannelParamStr(listToJson(channelParamList));
            agreementChannelVo.setPointParamStr(listToJson(pointParamList));

            voList.add(agreementChannelVo);
        }
        return new PageResult<>(page.getTotal(),voList);
    }

    @Override
    public AgreementChannelVo detail(String channelId) {
        AgreementChannel agreementChannel = agreementChannelMapper.selectById(channelId);
        AgreementChannelVo agreementChannelVo = AgreementChannelConvert.INSTANCE.agreementChannelToAgreementChannelVo(agreementChannel);
        //查询关联参数信息
        QueryWrapper<ChannelField> query = new QueryWrapper<>();
        query.lambda().eq(ChannelField::getChannelId,channelId);
        List<ChannelField> channelFieldList = channelFieldService.list(query);
        Map<Integer, List<ChannelField>> map = channelFieldList.stream().collect(Collectors.groupingBy(ChannelField::getFieldType));
        agreementChannelVo.setChannelParamList(map.get(0));
        agreementChannelVo.setPointParamList(map.get(1));
        return agreementChannelVo;
    }

    private String listToJson(List<ChannelField> paramList) {
        Map<String, String> map = paramList.stream().collect(Collectors.toMap(ChannelField::getFieldCode, ChannelField::getFieldName));
        return JsonUtils.toJSONString(map);
    }

    private void checkName(AgreementChannelDto agreementChannelDto) {
        String channelName = agreementChannelDto.getChannelName();
        String channelId = agreementChannelDto.getChannelId();
        QueryWrapper<AgreementChannel> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(AgreementChannel::getChannelName,channelName);
        if (StrUtil.isNotEmpty(channelId)) {
            queryWrapper.lambda().ne(AgreementChannel::getChannelId,channelId);
        }
        Long count = agreementChannelMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new ConditionException("通道名称不能重复，请修改后再保存");
        }
    }
}
